<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数字人视频播放器</title>
<style>
    html, body {
        height: 100%;
        margin: 0; /* 移除默认的边距 */
    }
    body {
        background-color: #008000;
        display: flex; /* 使用Flexbox布局使内容可以垂直居中 */
        justify-content: center; /* 水平居中 */
        align-items: center; /* 垂直居中 */
    }
    video {
        width: 100%;
        height: 100%;
        display: none; /* Initially hide both videos */
    }
</style>
</head>
<body>

<video id="video1" autoplay></video>
<video id="video2"></video>

<script>
    let video1 = document.getElementById('video1');
    let video2 = document.getElementById('video2');

    let videoQueue = []; // 视频播放队列
    let defaultVideo = ''; // 默认视频路径
    let currentVideo = video1; // 当前播放的视频元素
    let nextVideo = video2; // 下一个将要播放的视频元素
    let isWaitingForNextVideo = false; // 是否正在等待下一个视频加载
    let captions_printer_api_url = 'http://127.0.0.1:5500/send_message'; // 字幕打印机api地址

    // 设置配置
    function set_config(data) {
        if ("captions_printer_api_url" in data.data) {
            captions_printer_api_url = data.data.captions_printer_api_url;
            console.log("字幕打印机api地址已更新为：" + captions_printer_api_url);
        }
    }

    /**
     * 准备好下一个视频
     * @param {json} data - 下一个视频的路径等
     */
    function prepareNextVideo(data) {
        let src = data.video_path;

        if (!src) {
            console.log('默认视频不存在或未设置');
            switchVideos(data);
            return;
        }

        if (src === defaultVideo && isWaitingForNextVideo) {
            return; // 如果已经在播放默认视频且还在等待，则不重新加载默认视频
        }
        
        loadVideo(nextVideo, src, () => {
            if (src !== defaultVideo) console.log(src + '加载完成，准备播放');
            isWaitingForNextVideo = false; // 下一个视频已准备好，不再等待
            switchVideos(data);
        });
        
        if (src !== defaultVideo) {
            isWaitingForNextVideo = true; // 正在等待下一个视频加载，除非它是默认视频
            prepareNextVideo({"video_path": defaultVideo}); // 同时准备默认视频，以备需要时播放
        }
    }

    /**
     * 加载视频
     * @param {HTMLVideoElement} videoElement - 视频元素
     * @param {string} src - 视频路径
     * @param {Function} onLoadedCallback - 视频加载完成后的回调函数
     */
    function loadVideo(videoElement, src, onLoadedCallback) {
        videoElement.src = src;
        if (src !== defaultVideo) console.log('准备播放下一个视频：' + src);
        videoElement.load();
        videoElement.onerror = function() {
            console.log('加载视频失败：' + src);
            switchVideos(videoElement); // 加载失败时跳过当前视频，继续播放下一个视频
        };
        videoElement.onloadeddata = onLoadedCallback;

        // 加载字幕数据到字幕轨道

    }

    function getData(url, params = {}) {
        // 将参数对象转换为查询字符串
        const queryString = new URLSearchParams(params).toString();
        const fullUrl = `${url}?${queryString}`;

        return fetch(fullUrl, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        })
        .then(response => {
            // 检查响应是否成功
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json(); // 解析为 JSON
        })
        .catch(error => {
            console.error('请求失败:', error);
            throw error; // 将错误抛出，以便在调用时进行处理
        });
    }

    function postData(url, data = {}) {
        // 方法 1: 使用自定义的 replacer 函数
        const jsonString = JSON.stringify(data, (key, value) => {
            if (typeof value === 'string') {
                return value.replace(/\n/g, '\\n');
            }
            return value;
        });

        // 方法 2: 手动替换换行符 (如果方法 1 不起作用，可以尝试这种方法)
        // const jsonString = JSON.stringify(data).replace(/\\n/g, '\\n');

        return fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: jsonString
        })
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        })
        .catch(error => {
            console.error('请求失败:', error);
            throw error;
        });
    }

    /**
     * 切换视频
     */
    function switchVideos(data) {
        if (!isWaitingForNextVideo || currentVideo.src === defaultVideo) {
            // 只有当不再等待下一个视频，或当前视频是默认视频时才切换
            currentVideo.style.display = 'none';
            nextVideo.style.display = 'block';
            nextVideo.play();

            // 发送到字幕打印机
            if ("captions_printer" in data) {
                // 根据实际字幕打印机的接口进行修改
                postData(captions_printer_api_url, data.captions_printer)
                    .then(data => {
                        console.log('成功:', data);
                    })
                    .catch(error => {
                        console.error('错误:', error);
                    });
            }
            
            // 交换当前视频和下一个视频的引用
            [currentVideo, nextVideo] = [nextVideo, currentVideo];
        }
    }

    // 设置视频结束时的行为
    video1.onended = video2.onended = function() {
        // 存在1个以上说明还有视频需要播放，否则就是没了，需要删除已经完成播放的视频
        if (videoQueue.length > 1) {
            // 非默认视频情况下，删除掉已播放完的这个视频（此处在用户异常操作队列的情况下会有bug）
            if (!CurVideoisSameWithDefault()) videoQueue.shift();
            prepareNextVideo(videoQueue[0]); // 准备队列中的下一个视频
        } else {
            // 非默认视频情况下，删除掉已播放完的这个视频（此处在用户异常操作队列的情况下会有bug）
            if (videoQueue.length == 1 && !CurVideoisSameWithDefault()) {
                videoQueue.shift();
            } 
            // 如果当前视频是默认视频，那说明是第一次插入，则需要进行播放
            else if (videoQueue.length == 1 && CurVideoisSameWithDefault()) {
                prepareNextVideo(videoQueue[0]);
            } 

            if (!isWaitingForNextVideo) {
                console.log('播放默认视频');
                prepareNextVideo({"video_path": defaultVideo}); // 没有等待的视频，播放默认视频
            }
        }

        if (!currentVideo.src.includes(defaultVideo.substring(1))) {
            let nonDefaultVideoCount = getNonDefaultVideoCount();
            // 获取视频队列，发送给ws服务端同步数据
            getVideoQueue();
            // 当前视频播放完毕后，通过 WebSocket 回传视频路径
            const message = JSON.stringify({ type: 'videoEnded', count: nonDefaultVideoCount, video_path: currentVideo.src });
            ws.send(message);
        }
    };

    // WebSocket 接收视频路径并添加到队列
    const ws = new WebSocket('ws://localhost:8091/ws');
    ws.onopen = function(event) {
        console.log('WebSocket连接成功！');
        ws.send(JSON.stringify({ type: 'get_default_video' }));
    };
    ws.onmessage = function(event) {
        const data = JSON.parse(event.data);
        switch(data.type) {
            case 'show':
                handleShowMessage(data);
                break;
            case 'set_default_video':
                handleSetDefaultVideo(data);
                break;
            case 'stop_current_video':
                stopCurrentVideo(data);
                break;
            case 'get_non_default_video_count':
                getNonDefaultVideoCount(data);
                break;
            case 'get_video_queue':
                getVideoQueue();
                break;
            case 'del_video_with_index':
                delVideoWithIndex(data);
                break;    
            case 'set_config':
                set_config(data);
                break;
        }
    };

    /**
     * 处理 'show' 类型的消息
     * @param {Object} data - 消息数据
     */
    function handleShowMessage(data) {
        if (data.insert_index === 0) {
            videoQueue.unshift(data); // 将新视频添加到队首
        } else if (data.insert_index === -1) {
            videoQueue.push(data); // 将新视频添加到队尾
        } else {
            videoQueue.splice(data.insert_index, 0, data); // 插入指定位置
        }

        if (data.interrupt) { // 检查是否允许打断当前视频播放
            if (!CurVideoisSameWithDefault()) videoQueue.shift(); // 从队列中移除第一个视频
            prepareNextVideo(videoQueue[0]); // 如果允许打断，则立即准备下一个视频
        }

        let nonDefaultVideoCount = getNonDefaultVideoCount();

        ws.send(JSON.stringify({ code: 200, type: data.type, count: nonDefaultVideoCount, message: '播放成功' }));
    }

    /**
     * 处理 'set_default_video' 类型的消息
     * @param {Object} data - 消息数据
     */
    function handleSetDefaultVideo(data) {
        defaultVideo = data.video_path;
        // 初始化播放
        currentVideo.src = defaultVideo; // 初始视频
        currentVideo.load();
        currentVideo.play();
        currentVideo.style.display = 'block'; // 显示当前视频
    }

    /**
     * 立即停止当前视频并切换到下一个视频或默认视频
     */
    function stopCurrentVideo(data) {
        currentVideo.pause();
        currentVideo.currentTime = currentVideo.duration; // 模拟视频结束
        currentVideo.onended();
        ws.send(JSON.stringify({ code: 200, type: data.type, message: '停止当前播放成功' }));
    }

    function getNonDefaultVideoCount() {
        let nonDefaultVideoCount = videoQueue.filter(video => video.video_path !== defaultVideo).length;
        console.log("nonDefaultVideoCount:", nonDefaultVideoCount);
        console.log("currentVideo.src:", currentVideo.src);
        console.log("defaultVideo:", defaultVideo);
        if (!CurVideoisSameWithDefault()) {
            nonDefaultVideoCount += 1; // 如果当前视频不是默认视频，计入个数
        }
        ws.send(JSON.stringify({ code: 200, type: "get_non_default_video_count", count: nonDefaultVideoCount, message: '获取非默认视频数成功' }));
        return nonDefaultVideoCount;
    }

    // 获取视频播放列表数据
    function getVideoQueue() {
        ws.send(JSON.stringify({ code: 200, type: "get_video_queue", data: videoQueue, message: '获取视频播放列表成功' }));
        return videoQueue;
    }

    // 删除指定索引的视频数据
    function delVideoWithIndex(data) {
        let index = parseInt(data.index); // 将索引转换为整数
        videoQueue.splice(index, 1);
        ws.send(JSON.stringify({ code: 200, type: "del_video_with_index", data: videoQueue, message: '删除索引' + index + '的视频数据成功' }));
        return videoQueue;
    }

    // 当前播放视频是否和默认视频同名
    function CurVideoisSameWithDefault() {
        // 提取文件名的函数
        function getFilename(path) {
            return path.split('/').pop();
        }

        // 获取文件名
        const currentVideoFilename = getFilename(currentVideo.src);
        const defaultVideoFilename = getFilename(defaultVideo);

        // 比较文件名部分
        return currentVideoFilename === defaultVideoFilename;
    }

</script>

</body>
</html>
